# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, _


import logging
_logger = logging.getLogger(__name__)


# exclude, system fields, metadata, mail mail_activity mail.activity.mixin, mail mail.thread

excludes_base = [
            '__last_update',
            'create_date', 
            'create_uid', 
            'write_date', 
            'write_uid',
            'message_is_follower',
            'message_follower_ids',
            'message_partner_ids',
            'message_channel_ids',
            'message_ids',
            'message_unread',
            'message_unread_counter',
            'message_needaction',
            'message_needaction_counter',
            'message_has_error',
            'message_has_error_counter',
            'message_attachment_count',
            'message_main_attachment_id',
            'activity_ids',
            'activity_state',
            'activity_date_deadline',
            'activity_user_id',
            'activity_type_id',
            'activity_summary',
        ]

class OwIrModelFieldsExclude(models.Model):
    _name = 'ow.ir.model.fields.exclude'
    _description = "Ow Fields Exclude"
    _order = "module, model, name"

    name = fields.Char(string='Field Name')
    model = fields.Char(string='Model')
    module = fields.Char(string='Module')

    @api.model
    def _get_fields(self, model ):
        fields_meta = self.env[model].fields_get(None, ['type', 'relation'] )
        fields = self.search([('model','=',model)]).mapped('name') + excludes_base
        fields += [ key for key, val in fields_meta.items() if val['type'] == 'binary' ]
        return fields


class OwIrModelFieldsInclude(models.Model):
    _name = 'ow.ir.model.fields.include'
    _description = "Ow Fields Include"
    _order = "module, model, name"

    name = fields.Char(string='Field Name')
    model = fields.Char(string='Model')
    module = fields.Char(string='Module')

    @api.model
    def _get_fields(self, model ):
        return self.search([('model','=',model)]).mapped('name')
    

class OwIrModelFieldsConfig(models.AbstractModel):
    _name = 'ow.ir.model.fields.config'
    _description = "Ow Fields Config"

    def _fields_check(self, fields ):
        if not fields:
            fields = {}
        
        if isinstance(fields, list):
            fields = dict( (fld, None) for fld in fields )
        
        if not isinstance(fields, dict):
            # raise error
            pass
            
        return fields
        
    def _get_fields(self, model, fields ):
        includes = self.env['ow.ir.model.fields.include']._get_fields(model)
        excludes = self.env['ow.ir.model.fields.exclude']._get_fields(model)
        excludes = [ exc for exc in excludes if exc not in (includes + list(fields.keys()) ) ]
        fields_meta = self.env[model].fields_get(None, ['type', 'relation'] )
        return [ key for key in fields_meta if key not in excludes ]
        
    @api.model
    def fields_include(self, model, fields=None ):
        fields = self._fields_check(fields)
        fields_all = self._get_fields(model,fields)
        fields_meta = self.env[model].fields_get(None, ['type', 'relation'] )
        fields_ret = dict(( key, None) for key, val in fields_meta.items() if key in fields_all )
        
        for refk, refv in fields.items():
            ref_meta = fields_meta.get(refk)
            
            if not ref_meta:
                continue

            if ref_meta['type'] not in ['many2one','one2many','many2many']:
                continue
            
            fields_ret[refk] =  self.fields_include( ref_meta['relation'], refv)
        
        return fields_ret


    @api.model
    def fields_meta(self, model, fields=None, metas=None ):
        return self._get_fields_meta(model, fields, metas)

    def _get_fields_meta(self, model, fields=None, metas=None ):
        if not metas:
            metas = {}
            
        fields = self._fields_check(fields)
        if model in metas:
            return metas

        fields_meta = self.env[model].fields_get(None, ['type', 'relation'] )
        
        if not metas.get(model):
            metas[model] = fields_meta
        
        for refk, refv in fields.items():
            ref_meta = fields_meta.get(refk)
            if not ref_meta:
                continue

            if ref_meta['type'] not in ['many2one','one2many','many2many']:
                continue
            
            self._get_fields_meta( ref_meta['relation'], refv, metas)
            
        return metas

"""

    @api.model
    def fields_include_meta2(self, model, fields=None, metas=None ):
        if not metas:
            metas = {}
            
        fields = self._fields_check(fields)
        if model in metas:
            if not [ fld for fld in fields if fld not in metas[model] ]:
                return metas

        fields_all = self._get_fields(model,fields)
        fields_meta = self.env[model].fields_get(None, ['type', 'relation'] )
        fields_ret = dict(( key, val) for key, val in fields_meta.items() if key in fields_all )
        
        if metas.get(model):
            metas[model].update({model: fields_ret })
        else:
            metas[model] = fields_ret
        
        for refk, refv in fields.items():
            ref_meta = fields_meta.get(refk)
            if not ref_meta:
                continue

            if ref_meta['type'] not in ['many2one','one2many','many2many']:
                continue
            
            self.fields_include_meta( ref_meta['relation'], refv, metas)
            
        return metas

"""

